﻿package benny.ApkposStore.utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.zip.GZIPInputStream;

import org.apache.http.util.ByteArrayBuffer;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;
import android.util.Log;

/**
 * @date 创建时间：2012-1-10 下午3:51:37
 * @Description: 常用的网络操作请求函数
 * @author zijianlu
 */


public class NetUtils {
    private static final String TAG = "NetUtils";
    public static final String DEF_CODE = "UTF-8";

    private static ConnectivityManager mConnectManager = null;
    private static int mConnectTimeOut = 10 * 1000;
    private static int mReadTimeOut = 10 * 1000;
    
    public interface NetProgress
    {
    	public void onNetProgress(int total, int already);
    }

    /** 初始化 */
    public static void init(Context context) {
        if (mConnectManager == null) {
            mConnectManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        }
    }

    /** 设置超时时间 */
    public static void setTimeOut(int connTimeOut, int readTimeOut) {
        if (connTimeOut > 0 && readTimeOut > 0) {
            mConnectTimeOut = connTimeOut;
            mReadTimeOut = readTimeOut;
        }
    }

    /**
     * 获取网络连接,默认get方式连接
     * @throws IOException
     */
    public static HttpURLConnection getHttpConnection(String urlString)
        throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = null;

        connection = (HttpURLConnection) url.openConnection();

        connection.setConnectTimeout(mConnectTimeOut);
        connection.setReadTimeout(mReadTimeOut);

        return connection;
    }

    /**
     * 获取网络连接, post方式
     * @throws Exception
     */
    public static HttpURLConnection getHttpPostConnection(String urlString,
        String charSet) throws Exception {
        HttpURLConnection connection = getHttpConnection(urlString);
        connection.setDoInput(true);// 允许输入
        connection.setDoOutput(true);// 允许输出
        connection.setUseCaches(false);// 不使用Cache
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Charset", charSet);
        connection.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded");
        connection.addRequestProperty("Accept-Encoding", "gzip, deflate");
        return connection;
    }

    /**
     * 获取网络连接, post方式
     * @throws Exception
     */
    public static HttpURLConnection getHttpPostConnection(String urlString)
        throws Exception {
        return getHttpPostConnection(urlString, DEF_CODE);
    }

    /**
     * 用post方式获取文本数据 , 请求时要求服务器返回压缩流
     * @param 要上传的参数值
     */
    public static String fetchTextFromPost(String url, String params,
        String encode) throws Exception {

        byte[] bytes = fetchByteArrayFromPost(url, params);
        if (bytes != null) {
            return new String(bytes, encode);
        }
        return "";
    }

    /**
     * 用get方式获取文本数据 , 请求时要求服务器返回压缩流
     * @param 要上传的参数值
     */
    public static String fetchTextFromGet(String url, String encode)
        throws Exception {
        byte[] bytes = fetchByteArrayFromGet(url);
        if (bytes != null) {
            return new String(bytes, encode);
        }
        return "";
    }

    /**
     * 用get方式获取文本数据 , 请求时要求服务器返回压缩流
     * @param 要上传的参数值
     */
    public static String fetchTextFromGet(String url) throws Exception {
        byte[] bytes = fetchByteArrayFromGet(url);
        if (bytes != null) {
            return new String(bytes, DEF_CODE);
        }
        return "";
    }

    /**
     * 用post方式获取数据 , 请求时要求服务器返回压缩流
     * @param 要上传的参数值
     */
    public static String fetchTextFromPost(String url, String params)
        throws Exception {
        return fetchTextFromPost(url, params, DEF_CODE);
    }

    
    /**
	 * post方式获取数据，带下载进度回调
     * @return
     */
    public static byte[] fetchByteArrayFromPost(String url, String params, NetProgress netProgress)
    	throws Exception 
    {
        Log.d(TAG, "fetchByteArrayFromPost, params:" + params);
        DataOutputStream outputStream = null;
        HttpURLConnection connection = null;
        try {
            connection = getHttpPostConnection(url);
            
            outputStream = new DataOutputStream(connection.getOutputStream());
            outputStream.write(params.getBytes());// 发送表单字段数据
            outputStream.flush();

            int retCode = connection.getResponseCode();
            int length = connection.getContentLength();
            Log.d(TAG, "retCode:" + retCode + " length:" + length);
            if (retCode == 200) {
                String encode = connection.getContentEncoding();
                return inputStream2ByteArray(connection.getInputStream(),
                    encode, netProgress, length);
            }

        } finally {
            if (connection != null) {
                connection.disconnect();
            }

            if (outputStream != null) {
                try {
                    outputStream.close();
                    outputStream = null;
                } catch (IOException e) {
                }
            }
        }

        return null;   	
    }
    
    /**
     * 用post方式获取数据
     * @param 要上传的参数值
     */
    public static byte[] fetchByteArrayFromPost(String url, String params)
        throws Exception {
    	return fetchByteArrayFromPost(url, params, null);
    }

    public static byte[] fetchByteArrayFromGet(String url) throws Exception {
        HttpURLConnection connection = null;
        try {
            connection = getHttpConnection(url);
            connection.addRequestProperty("Accept-Encoding", "gzip, deflate");
            int retCode = connection.getResponseCode();
            int length = connection.getContentLength();
            Log.d(TAG, "fetchByteArrayFromGet, retCode:" + retCode + " length:"
                + length);
            if (retCode == 200) {
                String encode = connection.getContentEncoding();
                return inputStream2ByteArray(connection.getInputStream(),
                    encode, null, length);
            }
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return null;
    }

    /** 是否是wifi网络 */
    public static boolean isWiFiActive() {
        NetworkInfo info = mConnectManager.getActiveNetworkInfo();
        if (info != null) {
            String netType = info.getTypeName();
            if ("WIFI".equalsIgnoreCase(netType)) {
                return true;
            }
        }
        return false;
    }

    /** 网络是否可用 */
    public static boolean isNetworkActive() {
        NetworkInfo networkInfo = mConnectManager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isAvailable()
            && networkInfo.isConnected()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 将流转换成string, 支持压缩流解压, 默认UTF-8编码
     * @throws IOException
     */
    public static String inputStream2String(InputStream inputStream,
        String connectEncode) throws IOException {
        return inputStream2String(inputStream, connectEncode, DEF_CODE);
    }

    /**
     * 将流转换成string, 支持压缩流解压
     * @param connectEncode http回应中的 content-type字段的值
     * streamEncode 字符的编码
     * @throws IOException
     */
    public static String inputStream2String(InputStream inputStream,
        String connectEncode, String streamEncode) throws IOException {
        BufferedReader bufReader = null;

        if (!TextUtils.isEmpty(connectEncode) && connectEncode.contains("gzip")) {
            bufReader = new BufferedReader(new InputStreamReader(
                new GZIPInputStream(inputStream), streamEncode));
        } else {
            bufReader = new BufferedReader(new InputStreamReader(inputStream,
                streamEncode));
        }

        StringBuilder response = new StringBuilder();
        String line = "";
        try {
            while ((line = bufReader.readLine()) != null) {
                response.append(line);
            }
        } finally {
            if (bufReader != null) {
                bufReader.close();
            }
        }
        return response.toString();
    }

    /**
     * 将流转换成字节数组
     * @param connectEncode http回应中的 content-type字段的值
     * @throws IOException
     */
    public static byte[] inputStream2ByteArray(InputStream input,
        String connectEncode, NetProgress netProgress, int contentLength) throws IOException {

        if (input == null) {
            return null;
        }
        InputStream inputStream = null;
        if (!TextUtils.isEmpty(connectEncode) && connectEncode.contains("gzip")) {
            inputStream = new GZIPInputStream(input);
        } else {
            inputStream = input;
        }

        long t1 = System.currentTimeMillis();
        ByteArrayBuffer bytes = new ByteArrayBuffer(20 * 1024);

        byte[] buf = new byte[20 * 1024];
        int len = 0;

        try {
        	int already = 0;
            while ((len = inputStream.read(buf)) != -1) {
                bytes.append(buf, 0, len);
                already += len;
                if(netProgress != null) {
                	netProgress.onNetProgress(contentLength, already);
                }
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }

        long t2 = System.currentTimeMillis();
        Log.d(TAG, "inputStream2ByteArray:" + (t2 - t1));
        return bytes.toByteArray();
    }
}
